﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

using System.Drawing;
using Microsoft.DirectX;

using NGE;
using MH.GUI;

namespace MH
{
    public class SceneComponent : Component
    {
        public SceneComponent(string name, Game g)
            : base(name, g)
        {
            IsShowExtendTile = true; 
            IsInBattle = false;
        }

        ScriptComponent scriptCOM
        {
            get
            {
                return ((ScriptComponent)game.GetComponent("ScriptCOM"));
            }
        }
        //AnimationComponent aniCOM
        //{
        //    get
        //    {
        //        return ((AnimationComponent)game.GetComponent("AnimationCOM"));
        //    }
        //}

        public bool IsShowExtendTile;
        public bool IsInBattle;
        public bool IsFighting;
        protected int frameIndex = 0;

        #region for scene
        public Scene SCN;
        public Scene LoadScene(string file)
        {

            {
                FileIndexer fi = new FileIndexer(file);

                if (fi.PathName == string.Empty)
                {
                    fi = new FileIndexer(game.Option.ScenePath + file);
                }
                Scene scn;
                if (fi.ExtName == ".nscn")
                {
                    scn = (Scene)Util.LoadObject(fi.FullPathAndFileName);
                }
                else if (fi.ExtName == ".xml")
                {
                    scn = (Scene)Util.LoadObjectXML(fi.FullPathAndFileName, typeof(Scene));
                }
                else
                {
                    return null;
                }
                //scnPath = fi.PathName;
                //LoadScene(scn, chrLoc, chrDir);
                scn.Name = fi.FileName + fi.ExtName;
                return scn;
            }
        }
        public void EnterScene(Scene scn)
        {
            //if (PC == null)
            //{ }
            //else
            //{
            //    pc_dead_script = "";
            //    pc_dead_script += "fallout 500\n";
            //    pc_dead_script += "delay 500\n";

            //    pc_dead_script += "#pc_name hp+ " + PC.HPMax + "\n";
            //    pc_dead_script += "#pc_name enter mh-009.nscn 7 17 u\n";
            //    pc_dead_script += "npc01 fly 7 18 u\n";

            //    pc_dead_script += "fallin 500\n";
            //    pc_dead_script += "delay 500\n";

            //    pc_dead_script += "#pc_name palsy\n";
            //    pc_dead_script += "#pc_name move u 10\n";
            //    pc_dead_script += "npc01 move u 10\n";
            //    pc_dead_script += "block #pc_name nothing\n";
            //    pc_dead_script += "#pc_name notpalsy\n";
            //}

            ClearNPCs();
            ClearDoors();


            if (SCN != null)
            {
                SCN.Dispose();
            }
            game.Graph.FreeVideoMemory();

            //battleReset();

            if (scriptCOM != null)
            {
                if (scn.MusicFileName != "non_music" && scn.MusicFileName != "")
                {
                    scriptCOM.SetValue("bg_music", scn.MusicFileName);
                    scriptCOM.IS("music loop " + game.Option.SoundPath + scn.MusicFileName);
                }
                else
                {
                    scriptCOM.IS("music out");
                }
            }

            if (scn.NPCs == null)
            {
                scn.NPCs = new List<Character>();
            }
            foreach (Character npc in scn.NPCs)
            {
                npc.Location = npc.DefaultLocation;
                npc.RestoreDirection();
                npc.RestoreDoorState();
                //npc.IsSleeping = true;
                //string fn = npc.Name.Substring(0, npc.Name.Length - 1);
                //try
                //{
                //    npc.AvatarReady = (NAnimation)Util.LoadObject("data\\animation\\" + fn + "-stand.nani");
                //}
                //catch { }
                //try
                //{
                //    npc.AvatarFight = (NAnimation)Util.LoadObject("data\\animation\\" + fn + "-fight.nani");
                //}
                //catch { }
                //try
                //{
                //    npc.AvatarHit = (NAnimation)Util.LoadObject("data\\animation\\" + fn + "-hit.nani");
                //}
                //catch { }
                //try
                //{
                //    npc.AvatarWeapon = (NAnimation)Util.LoadObject("data\\animation\\" + fn + "-weapon.nani");
                //}
                //catch { }
                CHRs.Add(npc);
                //npc.AvatarSize = game.SCN.TileSize;
            }



            if (SCN != null)
                SCN.NPCs = null;

            //if (scn.OPCs == null)
            //{
            //    scn.OPCs = new List<PlayerCharacter>();
            //}

            SCN = scn;

            if (scriptCOM == null)
            {
                return;
            }
            scriptCOM.AS(SCN.LoadScript);
        }
        public void SceneFocusAt(Vector3 loc)
        {
            Vector3 cp = new Microsoft.DirectX.Vector3(game.Option.WindowSize.Width / SCN.TileSize.Width / 2 / (int)game.Option.Zoom, game.Option.WindowSize.Height / SCN.TileSize.Height / 2 / (int)game.Option.Zoom, 0);
            SCN.JumpTo(loc, cp);
        }
        #endregion

        #region for prop
        public Props Props;
        public Props LoadProps(string file)
        {
            FileIndexer fi = new FileIndexer(file);

            if (fi.PathName == string.Empty)
            {
                fi = new FileIndexer(game.Option.PropPath + file);
            }

            if (fi.ExtName == ".nprp")
            {
                return (Props)Util.LoadObject(fi.FullPathAndFileName);
            }
            return null;
        }
        #endregion

        #region for character
        public List<Character> CHRs = new List<Character>();
        public int PlayerCharacterIndex = -1;
        public Character PC
        {
            get
            {
                if (PlayerCharacterIndex < 0)
                {
                    try
                    {
                        PlayerCharacterIndex = GetCHRIndex(scriptCOM.GetValue("pc_name"));
                    }
                    catch
                    {
                        return null;
                    }
                    if (PlayerCharacterIndex < 0)
                    {
                        return null;
                    }
                }
                return CHRs[PlayerCharacterIndex];
            }
        }
        public int GetCHRIndex(string name)
        {
            if (CHRs.Count == 0)
            {
                return -1;
            }
            int i = 0;
            foreach (Character chr in CHRs)
            {
                if (name == chr.Name)
                {
                    return i;
                }
                i++;
            }
            
            return -1;
        }
        public Character GetCHR(string name)
        {
            int i = GetCHRIndex(name);
            if (i < 0)
            {
                return null;
            }
            return CHRs[i];
        }
        public Character GetCHR(int index)
        {

            return CHRs[index];
        }
        public Character GetCHR(Vector3 loc)
        {
            if (CHRs == null)
            {
                return null;
            }
            for (int i = 0; i < CHRs.Count; i++)
            {
                if (CHRs[i].Location == loc)
                {
                    return CHRs[i];
                }
            }
            return null;
        }
        public Character GetCHR(Vector3 loc,string is_not_name)
        {
            if (CHRs == null)
            {
                return null;
            }
            for (int i = 0; i < CHRs.Count; i++)
            {
                if (CHRs[i].Location == loc && CHRs[i].Name != is_not_name)
                {
                    return CHRs[i];
                }
            }
            return null;
        }
        public void SetCHR(Character pc, int x, int y, Direction chrDir)
        {
            SetCHR(pc, new Vector3(x, y, 0), chrDir);
        }
        public void SetCHR(Character pc, Vector3 chrLoc, Direction chrDir)
        {
            if (pc == null)
            {
                return;
            }
            pc.ClearCommandQueue();
            pc.InSceneName = SCN.Name;
            pc.MountEventHandler(OnPlayerCharacterActCode);

            if (pc.DrivingMetal != null)
            {
                pc.DrivingMetal.InSceneName = SCN.Name;
            }

            SetCHR(pc, chrLoc);
            SetCHR(pc, chrDir);

            //pc.IsFreezing = false;
        }
        void SetCHR(Character pc, Vector3 loc)
        {
            if (SCN == null)
            {
                return;
            }
            if (pc == null)
            {
                return;
            }
            pc.JumpTo(loc, SCN.TileSize);
            //Vector3 cp = new Microsoft.DirectX.Vector3(game.Option.WindowSize.Width / SCN.TileSize.Width / 2 / (int)game.Option.Zoom, game.Option.WindowSize.Height / SCN.TileSize.Height / 2 / (int)game.Option.Zoom, 0);
            //if (pc.Type == SpriteType.PC)
            //{
            //    SCN.JumpTo(loc, cp);
            //}
        }
        void SetCHR(Character pc, Direction dir)
        {
            pc.Direction = dir;
        }
        public void ClearNPCs()
        {
            int imax = CHRs.Count;
            for (int i = 0; i < imax; i++)
            {
                if (CHRs[i].Type == SpriteType.NPC || CHRs[i].Type == SpriteType.Monster)
                {
                    CHRs.RemoveAt(i);
                    i--;
                    imax--;
                }
            }
        }
        public void ClearDoors()
        {
            int imax = CHRs.Count;
            for (int i = 0; i < imax; i++)
            {
                if (CHRs[i].Type == SpriteType.Door)
                {
                    CHRs.RemoveAt(i);
                    i--;
                    imax--;
                }
            }
        }
        public Metal GetMetal(Character PC, Vector3 loc, Size tileSize)
        {
            if (PC == null)
            {
                return null;
            }
            for (int i = 0; i < PC.MetalCount; i++)
            {
                Metal mtl = PC.GetMetal(i);
                Vector3 v3 = mtl.StopLocation;
                if (mtl.StopDirection == Direction.U)
                { }
                else if (mtl.StopDirection == Direction.L)
                {
                    //v3.Y += TileSize.Height;
                }
                else if (mtl.StopDirection == Direction.D)
                {
                    v3.X += tileSize.Width;
                    //v3.Y += TileSize.Height;
                }
                else if (mtl.StopDirection == Direction.R)
                {
                    v3.X += tileSize.Width;
                }
                if (v3.Equals(loc))
                {
                    return mtl;
                }
            }
            //if (OPCs == null)
            //{
            //    return null;
            //}
            //foreach (PlayerCharacter chr in OPCs)
            //{
            //    for (int i = 0; i < chr.MetalCount; i++)
            //    {
            //        Metal mtl = chr.GetMetal(i);
            //        if (mtl.StopLocation.Equals(loc))
            //        {
            //            return mtl;
            //        }
            //    }
            //}

            return null;
        }
        #endregion

        #region for battle
        public Queue<int> ActQue = new Queue<int>();
        public List<Character> Monsters = new List<Character>();
        public List<Character> LoadMonsters(string file)
        {
            FileIndexer fi = new FileIndexer(file);

            if (fi.PathName == string.Empty)
            {
                fi = new FileIndexer(game.Option.CharacterPath + file);
            }

            if (fi.ExtName == ".nchrs")
            {
                return (List<Character>)Util.LoadObject(fi.FullPathAndFileName);
            }
            return null;
        }
        int GetMonsterIndex(string monName)
        {
            for (int i = 0; i < Monsters.Count; i++)
            {
                if (Monsters[i].Name == monName)
                {
                    return i;
                }
            }
            return -1;
        }
        public List<Character> MonstersInBattle = new List<Character>();
        List<Vector3> MonstersLocation = new List<Vector3>();
        List<Vector3> BattleManLocation = new List<Vector3>();
        void initBattle(MonsterCode mc)
        {
            if (mc.BattleMusic != "non_music" && mc.BattleMusic != "")
            {
                scriptCOM.SetValue("bg_music", mc.BattleMusic);
                scriptCOM.IS("music loop " + game.Option.SoundPath + mc.BattleMusic);
            }
            else
            {
                scriptCOM.IS("music out");
            }
            MonstersLocation.Clear();
            for (int i = 0; i < 3; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    Vector3 loc = new Vector3(36 + i * 48, 36 + j * 48, 0);
                    MonstersLocation.Add(loc);
                }
            }

            BattleManLocation.Clear();
            for (int j = 0; j < 4; j++)
            {
                Vector3 loc = new Vector3(256, 36 + j * 48, 0);
                BattleManLocation.Add(loc);
            }
            //{
                //int seed = Util.Roll(1, 10000);
                //if (seed <= mc.BattleRate)
                //{
                //    seed = Util.Roll(1, 12);
                //    int kind = Util.Roll(1, 10);
                //    if (kind < 7)
                //    {
                //        kind = 1;
                //    }
                //    else if (kind < 10)
                //    {
                //        kind = 2;
                //    }
                //    else
                //    {
                //        kind = 3;
                //    }
                //    mc.
                    //if (kind > mc..Count)
                    //{
                    //    kind = MonsterCodeSet.Count;
                    //}

                    //int mc = 0;
                    //for (int j = 0; j < kind; j++)
                    //{
                    //    int s = Util.Roll(0, MonsterCodeSet.Count - 1);
                    //    int n = Util.Roll(1, seed - mc);

                    //    if (mc == seed)
                    //    {
                    //        break;
                    //    }
                    //    for (int k = 0; k < n; k++)
                    //    {
                    //        tmp.Add(MonsterCodeSet[i].MonsterNames[s]);
                    //    }
                    //    mc += n;
                    //}
                    //return tmp;
            //    }
            //}
            for (int i = 0; i < mc.MonsterNames.Count; i++)
            {
                int j = GetMonsterIndex(mc.MonsterNames[i]);
                MonstersInBattle.Add(Monsters[j]);
                
                //aniCOM.DrawAnimation(monNames[i] + i, Monsters[j].AvatarReady, loc, loc, 0, true, 1000, false);
            }

            IsInBattle = true;
        }

        public int GetMONIndex(string name)
        {
            if (CHRs.Count == 0)
            {
                return -1;
            }
            int i = 0;
            foreach (Character chr in MonstersInBattle)
            {
                if (name == chr.Name)
                {
                    return i;
                }
                i++;
            }

            return -1;
        }
        #endregion


        #region draw
        protected void drawSCN(Scene scn, List<Character> chrs)
        {
            if (scn == null)
            {
                return;
            }
            if (IsShowExtendTile)
            {
                #region extend tile
                if (scn.ExtendTile != null)
                {
                    for (int y = -scn.TileSize.Height; y <= game.Option.WindowSize.Height / game.Option.Zoom; y += scn.TileSize.Height)
                    {
                        //left
                        for (int x = scn.TileSize.Width; x <= scn.Location.X + scn.TileSize.Width; x += scn.TileSize.Width)
                        {
                            Vector3 v3 = new Vector3(-x, y, 0);

                            v3.X += scn.Location.X;
                            v3.Y += scn.Location.Y % scn.TileSize.Height;

                            int i = frameIndex % scn.ExtendTile.Frames.Count;

                            v3 = Util.Vector3AddVector3(v3, Vector3Offset);
                            game.Graph.DrawImage(scn.TileImageSet[scn.ExtendTile.Frames[i].TextureIndexer.Index], FilterColor, v3);
                        }
                        //right
                        int xmax = (int)((game.Option.WindowSize.Width / game.Option.Zoom) - (scn.Location.X + scn.Size.Width * scn.TileSize.Width));
                        for (int x = 0; x <= xmax; x += scn.TileSize.Width)
                        {
                            Vector3 v3 = new Vector3(x, y, 0);
                            v3.X += scn.Location.X;
                            v3.Y += scn.Location.Y % scn.TileSize.Height;

                            v3.X += scn.Size.Width * scn.TileSize.Width;

                            int i = frameIndex % scn.ExtendTile.Frames.Count;
                            v3 = Util.Vector3AddVector3(v3, Vector3Offset);
                            game.Graph.DrawImage(scn.TileImageSet[scn.ExtendTile.Frames[i].TextureIndexer.Index], FilterColor, v3);
                        }
                    }
                    for (int x = 0; x < scn.Size.Width * scn.TileSize.Width; x += scn.TileSize.Width)
                    {
                        //top
                        for (int y = 0; y < scn.Location.Y; y += scn.TileSize.Height)
                        {
                            Vector3 v3 = new Vector3(x, -y, 0);
                            v3 = Util.Vector3AddVector3(v3, scn.Location);

                            v3.Y -= scn.TileSize.Height;

                            int i = frameIndex % scn.ExtendTile.Frames.Count;
                            v3 = Util.Vector3AddVector3(v3, Vector3Offset);
                            game.Graph.DrawImage(scn.TileImageSet[scn.ExtendTile.Frames[i].TextureIndexer.Index], FilterColor, v3);

                        }
                        //bottom
                        int ymax = (int)(game.Option.WindowSize.Height / game.Option.Zoom - (scn.Location.Y + scn.Size.Height * scn.TileSize.Height));
                        for (int y = 0; y <= ymax; y += scn.TileSize.Height)
                        {
                            Vector3 v3 = new Vector3(x, y, 0);
                            v3 = Util.Vector3AddVector3(v3, scn.Location);

                            v3.Y += scn.Size.Height * scn.TileSize.Height;

                            int i = frameIndex % scn.ExtendTile.Frames.Count;
                            v3 = Util.Vector3AddVector3(v3, Vector3Offset);
                            game.Graph.DrawImage(scn.TileImageSet[scn.ExtendTile.Frames[i].TextureIndexer.Index], FilterColor, v3);
                        }
                    }
                }
                #endregion
            }
            int layerIndex = 0;
            foreach (Terrain.Layer layer in SCN.Terrain.Layers)
            {
                if (layer.Visible)
                {
                    if (PC != null)
                    {
                        //if (layerIndex == 2)
                        //{
                        //    drawNPCs(scn, CHRs);
                        //    drawDoors(scn, CHRs);
                        //}
                        foreach (Terrain.Layer.Tile tile in layer.Tiles)
                        {
                            Vector3 v3 = Util.Vector3AddVector3(scn.Location, tile.Location);
                            if (v3.X < 0 - scn.TileSize.Width || v3.X > game.Option.WindowSize.Width / game.Option.Zoom || v3.Y < 0 - scn.TileSize.Height || v3.Y > game.Option.WindowSize.Height / game.Option.Zoom)
                            {
                                continue;
                            }
                            if (tile.Location.Y <= PC.Location.Y)
                            {
                                int i = frameIndex % tile.Frames.Count;
                                if (i > -1)
                                {
                                    i = tile.Frames[i].TextureIndexer.Index;
                                    if (i < scn.TileImageSet.Count)
                                    {
                                        v3 = Util.Vector3AddVector3(v3, Vector3Offset);
                                        game.Graph.DrawImage(scn.TileImageSet[i], FilterColor, v3);
                                    }
                                }
                            }
                        }
                        if (layerIndex == 3)
                        {
                            //drawZones(scn, chrs);
                            //drawSpritesAttackZone(scn, pc, opcs);
                            drawNPCs(scn, CHRs);

                            drawMTLs(scn, PC);
                            drawPC(scn, PC);
                          
                            //drawOPCs(scn, opcs);
                            drawDoors(scn, CHRs);
                        }
                        foreach (Terrain.Layer.Tile tile in layer.Tiles)
                        {
                            Vector3 v3 = Util.Vector3AddVector3(scn.Location, tile.Location);
                            if (v3.X < 0 - scn.TileSize.Width || v3.X > game.Option.WindowSize.Width / game.Option.Zoom || v3.Y < 0 - scn.TileSize.Height || v3.Y > game.Option.WindowSize.Height / game.Option.Zoom)
                            {
                                continue;
                            }
                            if (tile.Location.Y > PC.Location.Y)
                            {
                                int i = frameIndex % tile.Frames.Count;
                                if (i > -1)
                                {
                                    i = tile.Frames[i].TextureIndexer.Index;
                                    if (i < scn.TileImageSet.Count)
                                    {
                                        v3 = Util.Vector3AddVector3(v3, Vector3Offset);
                                        game.Graph.DrawImage(scn.TileImageSet[i], FilterColor, v3);
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        if (layerIndex == 3)
                        {
                            drawNPCs(scn, CHRs);
                            drawDoors(scn, CHRs);
                        }
                        foreach (Terrain.Layer.Tile tile in layer.Tiles)
                        {
                            Vector3 v3 = Util.Vector3AddVector3(scn.Location, tile.Location);
                            if (v3.X < 0 - scn.TileSize.Width || v3.X > game.Option.WindowSize.Width / game.Option.Zoom || v3.Y < 0 - scn.TileSize.Height || v3.Y > game.Option.WindowSize.Height / game.Option.Zoom)
                            {
                                continue;
                            }
                            //if (tile.Location.Y <= chr.Location.Y)
                            {
                                int i = frameIndex % tile.Frames.Count;
                                if (i > -1)
                                {
                                    i = tile.Frames[i].TextureIndexer.Index;
                                    if (i < scn.TileImageSet.Count)
                                    {
                                        v3 = Util.Vector3AddVector3(v3, Vector3Offset);
                                        game.Graph.DrawImage(scn.TileImageSet[i], FilterColor, v3);
                                    }
                                }
                            }
                        }
                    }
                }
                layerIndex++;
            }
        }
        void drawDoor(Scene scn, Character door)
        {
            if (door == null)
            {
                return;
            }

            Vector3 v3 = Util.Vector3AddVector3(scn.Location, door.Location);
            v3.Y -= door.AvatarSize.Height - scn.TileSize.Height;
            Rectangle rect = new Rectangle();

            int i = (int)door.DoorState;
            rect.X = i * scn.TileSize.Width * door.AvatarSize.Width;
            rect.Y = 0;
            rect.Size = door.AvatarSize;

            v3 = Util.Vector3AddVector3(v3, Vector3Offset);
            game.Graph.DrawImage(door.Avatar, FilterColor, rect, v3,false);
        }
        void drawDoors(Scene scn, List<Character> npcs)
        {
            if (npcs == null)
            {
                return;
            }
            foreach (Character npc in npcs)
            {
                if (npc.Type == SpriteType.Door)
                {
                    drawDoor(scn, npc);
                }
            }
        }
        void drawSprite(Scene scn, Character chr)
        {
            if (chr == null)
            {
                return;
            }
            if (chr.IsHide)
            {
                return;
            }

            //drawMoveZone(scn, chr);
            //drawAttackZone(scn, chr);

            Vector3 v3 = Util.Vector3AddVector3(scn.Location, chr.Location);
            v3.Y -= chr.AvatarSize.Height - scn.TileSize.Height;
            Rectangle rect = new Rectangle();
            v3 = Util.Vector3AddVector3(v3, Vector3Offset);

            //bool isflip = false;
            //if (chr.Direction == Direction.R)
            //{
            //    isflip = true;
            //}
            /*
            if (chr.AvaterAct == CharacterAvaterActs.Ready)
            {
                //if (chr.AvatarReady != null)
                {
                    Vector3 v33 = Util.Vector3AddVector3(v3, new Vector3(scn.TileSize.Width / 2, scn.TileSize.Height, 0));

                    game.AnimationCOM.DrawAnimation(chr.Name + "ready", chr.AvatarReady, v33, -1, false, chr.AvatarFlip);
                }
            }
            else if (chr.AvaterAct == CharacterAvaterActs.Fight)
            {
                //if (chr.AvatarFight != null)
                {
                    if (game.AnimationCOM.Contains(chr.Name + "fight"))
                    {
                        if (game.AnimationCOM.AnimationIsStoped(chr.Name + "fight"))
                        {
                            chr.AvaterAct = CharacterAvaterActs.Stand;
                        }
                    }
                    else
                    {
                        if (game.AnimationCOM.Contains(chr.Name + "ready"))
                        {
                            game.AnimationCOM.ClearAnimation(chr.Name + "ready");
                        }
                        Vector3 v33 = Util.Vector3AddVector3(v3, new Vector3(scn.TileSize.Width / 2, scn.TileSize.Height, 0));


                        game.AnimationCOM.DrawAnimation(chr.Name + "fight", chr.AvatarFight, v33, 1, false, chr.AvatarFlip);
                    }
                }
            }
            else if (chr.AvaterAct == CharacterAvaterActs.Hit)
            {
                //if (chr.AvatarHit != null)
                {
                    if (game.AnimationCOM.Contains(chr.Name + "hit"))
                    {
                        if (game.AnimationCOM.AnimationIsStoped(chr.Name + "hit"))
                        {
                            chr.AvaterAct = CharacterAvaterActs.Stand;
                        }
                    }
                    else
                    {
                        if (game.AnimationCOM.Contains(chr.Name + "hit"))
                        {
                            game.AnimationCOM.ClearAnimation(chr.Name + "hit");
                        }
                        Vector3 v33 = Util.Vector3AddVector3(v3, new Vector3(scn.TileSize.Width / 2, scn.TileSize.Height, 0));
                        game.AnimationCOM.DrawAnimation(chr.Name + "hit", chr.AvatarHit, v33, 1, false, chr.AvatarFlip);
                    }
                }
            }*/

            //if (chr.AvaterAct == CharacterAvaterActs.Stand)
            {

                ////Color sc = FilterColor;
                //if (chr.IsDead)
                //{
                //    int tmp = FilterColor.ToArgb() & Color.MediumPurple.ToArgb();
                //    sc = Color.FromArgb(tmp);
                //}
                //game.AnimationCOM.ClearAnimationContains(chr.Name);
                if (chr.InMetalIndex < 0)
                {
                    rect.X = chr.GetAvatarFrame(scn.TileSize) * chr.AvatarSize.Width;
                    if (chr.IsPalsy)
                    {
                        rect.X = 0;
                    }
                    rect.Y = (int)chr.Direction * chr.AvatarSize.Height;
                    rect.Size = chr.AvatarSize;

                    game.Graph.DrawImage(chr.Avatar, FilterColor, rect, v3, false);
                }
                else
                {
                    rect.X = chr.GetAvatarFrame(scn.TileSize) * chr.DrivingMetal.AvatarSize.Width;
                    rect.Y = (int)chr.Direction * chr.DrivingMetal.AvatarSize.Height;
                    rect.Size = chr.DrivingMetal.AvatarSize;

                    //v3.X += 4;
                    //v3.Y -= 4;                
                    game.Graph.DrawImage(chr.DrivingMetal.Avatar, FilterColor, rect, v3, false);
                }
            }

            //else if (chr.BattleAct == CharacterActs.BattleAttackCommanding)
            //{
            //    //if (game.AnimationCOM.Contains(chr.Name))
            //    //{
            //    //    return;
            //    //}
            //    Vector3 v33 = Util.Vector3AddVector3(v3, new Vector3(scn.TileSize.Width / 2, scn.TileSize.Height, 0));
            //    game.AnimationCOM.DrawAnimation(chr.Name, chr.BattleReady, v33, -1,false);
            //}
            //else if (chr.BattleAct == CharacterActs.BattleFight)
            //{
            //    if (game.AnimationCOM.Contains(chr.Name))
            //    {
            //        if (game.AnimationCOM.AnimationIsStoped(chr.Name))
            //        {
            //            chr.BattleAct = CharacterActs.Nothing;
            //        }
            //    }
            //    else
            //    {
            //        Vector3 v33 = Util.Vector3AddVector3(v3, new Vector3(scn.TileSize.Width / 2, scn.TileSize.Height, 0));
            //        game.AnimationCOM.DrawAnimation(chr.Name, chr.BattleFight, v33, 1, false);
            //    }          
            //}


            //v3.Y -= 16;
            //game.Graph.DrawText(chr.Name, Color.Blue, v3);
            //if (game.RunningTotalSeconds - chr.SaidStartTime < chr.SaidDuration)
            //{
            //    v3.Y -= 32;
            //    v3.X -= 64;
            //    game.Graph.DrawText(chr.Said, Color.Blue, v3);
            //}
        }
        void drawPC(Scene scn, Character chr)
        {
            if (chr.Type == SpriteType.PC)
            {
                drawSprite(scn, chr);
            }
        }
        void drawNPCs(Scene scn, List<Character> npcs)
        {
            if (npcs == null)
            {
                return;
            }
            foreach (Character npc in npcs)
            {
                if (npc.Type == SpriteType.NPC || npc.Type == SpriteType.Monster)
                {
                    drawSprite(scn, npc);
                }
            }
        }
        void drawMTLs(Scene scn, Character chr)
        {
            if (chr == null)
            {
                return;
            }

            for (int i = 0; i < chr.MetalCount; i++)
            {
                Metal mtl = chr.GetMetal(i);
                if (mtl.InSceneName == scn.Name)
                {
                    if (mtl.IsRunning == false)
                    {
                        Vector3 v3 = Util.Vector3AddVector3(scn.Location, mtl.StopLocation);
                        //loc.Y -= chr.AvatarSize.Height - scn.TileSize.Height;
                        Rectangle rect = new Rectangle();

                        //rect.X = 0;
                        rect.Y = (int)mtl.StopDirection * mtl.AvatarSize.Height;
                        rect.Size = mtl.AvatarSize;
                        if (mtl.AvatarSize.Width > scn.TileSize.Width)
                        {
                            v3.X += 4;
                        }
                        if (mtl.AvatarSize.Height > scn.TileSize.Height)
                        {
                            v3.Y -= 4;
                        }

                        v3 = Util.Vector3AddVector3(v3, Vector3Offset);
                        game.Graph.DrawImage(mtl.Avatar, FilterColor, rect, v3, false);
                    }
                }
            }
        }
        //battle
        void drawMONs(List<Character> mons)
        {            
            for (int i=0;i<mons.Count;i++)
            {
                Character mon = mons[i];
                if (mon.AvatarAct == CharacterAvaterActs.Stand)
                {
                    game.Graph.DrawAnimation(mon.AvatarReady, Color.White, MonstersLocation[i], false, true, game.RunningTotalSeconds);
                }
                else if (mon.AvatarAct == CharacterAvaterActs.Fight)
                {
                    if (mon.LastAvatarAct != mon.AvatarAct)
                    {
                        mon.AvatarFight.Reset();
                    }
                    game.Graph.DrawAnimation(mon.AvatarFight, Color.White, MonstersLocation[i], false, false, game.RunningTotalSeconds);
                }
                mon.LastAvatarAct = mon.AvatarAct;
            }
        }
        void drawBattleMan(Character battleman,int index)
        {
            if (battleman.AvatarAct == CharacterAvaterActs.Stand)
            {                
                game.Graph.DrawAnimation(battleman.AvatarReady, Color.White, BattleManLocation[index], false, true, game.RunningTotalSeconds);
            }
            else if (battleman.AvatarAct == CharacterAvaterActs.Fight)
            {
                if (battleman.LastAvatarAct != battleman.AvatarAct)
                {
                    battleman.AvatarFight.Reset();
                }
                game.Graph.DrawAnimation(battleman.AvatarFight, Color.White, BattleManLocation[index], false, false, game.RunningTotalSeconds);
            }
            battleman.LastAvatarAct = battleman.AvatarAct;
        }
        #endregion

        public override void Heartbeat()
        {
            if (SCN == null)
            {
                return;
            }
            game.Timer.Record();
            if (game.Timer.Seconds > SCN.FrameInterval / 1000.0)
            {
                frameIndex++;
                game.Timer.Reset();
            }

            if (SCN == null)
            {
                return;
            }

            if (IsInBattle == false)
            {
                SCN.Heartbeat();

                for (int i = 0; i < CHRs.Count; i++)
                {
                    CHRs[i].Heartbeat(this);
                }
            }
            else
            {
                //战场行动队列中没有数据
                if (ActQue.Count == 0)
                {
                    //生成行动队列
                    int[] act_index = new int[MonstersInBattle.Count+1];
                    for (int i = 0; i < act_index.Length; i++)
                    {
                        act_index[i] = i;
                    }
                    do
                    {
                        int j = Util.Roll(0, act_index.Length - 1);

                        if (act_index[j] != 100)
                        {
                            ActQue.Enqueue(act_index[j]);
                            act_index[j] = 100;
                        }
                    }
                    while (ActQue.Count < act_index.Length);
                }
                else
                {
                    if (IsFighting)
                    {
                    }
                    else
                    {                        
                        int i = ActQue.Dequeue();
                        if (i >= MonstersInBattle.Count)
                        {
                            scriptCOM.AS("msg 0 0 " + PC.Name + "攻击");
                            scriptCOM.AS(PC.Name + " avatar fight");
                            scriptCOM.AS("delay 3000");
                            scriptCOM.AS("msg");
                            scriptCOM.AS(PC.Name + " avatar stand");
                            scriptCOM.AS("battle notbusy");
                        }
                        else
                        {
                            //MonstersInBattle[i].AvaterAct = CharacterAvaterActs.Fight;          
                            scriptCOM.AS("msg 0 0 " + MonstersInBattle[i].Name + "攻击");
                            scriptCOM.AS(MonstersInBattle[i].Name + " avatar fight");
                            scriptCOM.AS("delay 3000");
                            scriptCOM.AS("msg");
                            scriptCOM.AS(MonstersInBattle[i].Name + " avatar stand");
                            scriptCOM.AS("battle notbusy");
                        }
                        IsFighting = true;
                    }
                }
            }
        }

        public override void Show()
        {
            if (SCN == null)
            {
                return;
            }

            if (IsInBattle == false)
            {
                drawSCN(SCN, CHRs);
            }
            else
            {
                drawMONs(MonstersInBattle);
                drawBattleMan(PC, 0);
            }
        }
        
        public void OnPlayerCharacterActCode(object sender, CharacterEventArgs ea)
        {
            Character chr = (Character)sender;
            if (ea.Act == CharacterActs.ChangeDirection)
            {
                Datagram.PlayerCharacterMoveInfo pcmi = (Datagram.PlayerCharacterMoveInfo)ea.Arg;
                //if (game.IsOnline)
                //{
                //    pcmi.Steps = 0;
                //    game.ClientCOM.UploadPCMoveInfo(pcmi);
                //}
            }
            if (ea.Act == CharacterActs.StartMove)
            {
                if (chr.Type == SpriteType.PC)
                {
                    Datagram.PlayerCharacterMoveInfo pcmi = (Datagram.PlayerCharacterMoveInfo)ea.Arg;
                    SCN.Move(pcmi.Direction, pcmi.Steps, pcmi.MoveSpeed);
                }
                //if (game.IsOnline)
                //{
                //    game.ClientCOM.UploadPCMoveInfo(pcmi);
                //}
            }
            if (ea.Act == CharacterActs.StopMove)
            {
                //if (game.IsOnline)
                //{
                //    Datagram.PlayerCharacterSceneInfo pcsi = (Datagram.PlayerCharacterSceneInfo)ea.Arg;
                //    game.ClientCOM.UploadPCSceneInfo(pcsi);
                //}

            }
            if (ea.Act == CharacterActs.EnterScene)
            {
                Datagram.PlayerCharacterSceneInfo csi = (Datagram.PlayerCharacterSceneInfo)ea.Arg;
                string cmd = "";

                scriptCOM.AS("clrctrl");

                scriptCOM.AS(SCN.UnloadScript);

                cmd += "fallout 500\n";
                cmd += "delay 500\n";
                cmd += "#pc_name enter " + csi.InSceneName + " " + csi.Location.X + " " + csi.Location.Y + " " + csi.Direction.ToString().ToLower() + "\n";
                cmd += "fallin 500\n";
                cmd += "delay 500\n";
                scriptCOM.AS(cmd);                

                scriptCOM.AS("setctrl");
            }
            if (ea.Act == CharacterActs.EnterBattle)
            {
                Datagram.BattleMonsterInfo bmi = (Datagram.BattleMonsterInfo)ea.Arg;
                scriptCOM.AS("clrctrl");
                scriptCOM.AS("fallout 1");
                //scriptCOM.AS("delay 1000");
                //scriptCOM.AS("fallin 1");
                //scriptCOM.AS("setctrl");
                initBattle(bmi.MonsterCode);
            }
        }

        public override void OnKeyboardEventCode(object sender, int key, KeyboardState ks)
        {
            if (SCN == null)
            {
                return;
            }
            //if (haveEnemy && !allEnemySleep)
            //{
            //    return;
            //}         
            if (game.MenuCOM.IsBusy)
            {
                return;
            }
            if (ks == KeyboardState.KeyUp)
            {
                if (key == game.Option.KeyA)
                {
                    PC.Talk(SCN, CHRs, scriptCOM);
                }
                else if (key == game.Option.KeyB)
                {
                    scriptCOM.AS("menu open 玩家菜单");
                }
                else if (key == game.Option.KeyX)
                {
                    scriptCOM.AS("menu open 系统菜单");
                }
                else if (key == 59)
                {
                    //game.AnimationCOM.DrawAnimation("data\\animation\\boom.nani", new Vector3(50, 50, 0), new Vector3(50, 50, 0), false, 1000);
                    //game.AnimationCOM.ClearAnimation("ani1");
                    scriptCOM.AS("ani ani1 data\\animation\\boom.nani 1 autoclr noflip 50 50");
                }
                else if (key == 60)
                {
                    //game.AnimationCOM.DrawAnimation("data\\animation\\boom.nani", new Vector3(20, 20, 0), new Vector3(300, 200, 0), -1, false, 1000);
                }
            }
            else if (ks == KeyboardState.KeyHold)
            {
                if (key == game.Option.KeyU || key == game.Option.KeyL || key == game.Option.KeyD || key == game.Option.KeyR)
                {
                    //if (PC.IsFreezing)
                    //{
                    //    return;
                    //}
                    //if (PC.NeedMove > 0)
                    //{
                    //    return;
                    //}
                    int steps = 1;
                    Direction dir = Direction.U;
                    if (key == game.Option.KeyU)
                    {
                        dir = Direction.U;
                    }
                    else if (key == game.Option.KeyL)
                    {
                        dir = Direction.L;
                    }
                    else if (key == game.Option.KeyD)
                    {
                        dir = Direction.D;
                    }
                    else if (key == game.Option.KeyR)
                    {
                        dir = Direction.R;
                    }
                    PC.Move(dir, steps, SCN, CHRs);

                }
            }
        }

        /*
        #region for fight
        bool haveEnemy
        {
            get
            {
          
                if (CHRs == null)
                {
                    return false;
                }
                if (CHRs.Count == 0)
                {
                    return false;
                }
                foreach (Character npc in CHRs)
                {
                    if (npc.Type == SpriteType.Monster)
                    {
                        if (npc.IsDead == false)
                        {
                            return true;
                        }
                    }
                }
                return false;
            }
        }
        bool allEnemySleep
        {
            get
            {
                //if (CHRs == null)
                //{
                //    return false;
                //}
                //if (CHRs.Count == 0)
                //{
                //    return false;
                //}
                //foreach (Character npc in CHRs)
                //{
                //    if (npc.Type == SpriteType.Monster)
                //    {
                //        if (npc.IsSaw(SCN, PC.Location))
                //        {
                //            return true;
                //        }
                //    }
                //}
                //return false;            
                if (CHRs == null)
                {
                    return false;
                }
                if (CHRs.Count == 0)
                {
                    return false;
                }
                for (int i=0;i<CHRs.Count;i++)
                {
                    if (CHRs[i].Type == SpriteType.Monster)
                    {
                        if (!CHRs[i].IsSleeping && !CHRs[i].IsDead)
                        {
                            return false;
                        }
                    }
                }
                return true;
            }
        }

        //bool noMonsterCanSee()
        //{
        //    foreach (Character chr in CHRs)
        //    {
        //        if (chr.Type != SpriteType.PC)
        //        {
        //            if (!chr.IsDead)
        //            {
        //                if (chr.IsInCanSeeZone(7, 7, SCN, PC.Location))
        //                {
        //                    return false;
        //                }
        //            }
        //        }
        //    }
        //    return true;
        //}
        //void sleepAlertHB()
        //{
        //    while (true)
        //    {
        //        //if (sleepAlertRUN)
        //        {
        //            if (haveEnemy)
        //            {
        //                if (allEnemySleep)
        //                {
        //                    int i = 0;
        //                    for (i = 0; i < CHRs.Count; i++)
        //                    {
        //                        if (CHRs[i].Type == SpriteType.Monster || (CHRs[i].Type == SpriteType.NPC && CHRs[i].IsEnemy))
        //                        {
        //                            if (scriptCOM != null)
        //                            {
        //                                Character pc = GetCHR(scriptCOM.GetValue("pc_name"));
        //                                if (pc != null)
        //                                {
        //                                    if (CHRs[i].IsSaw(SCN, pc.Location))
        //                                    {
        //                                        CHRs[i].IsSleeping = false;
        //                                        if (BattleIsBusy)
        //                                        {
        //                                            //scriptCOM.AS("battle notbusy");
        //                                            BattleIsBusy = false;
        //                                        }
        //                                        break;
        //                                    }
        //                                }
        //                            }
        //                        }
        //                    }
        //                    if (i == CHRs.Count)
        //                    {
        //                        restoreBGM();
        //                    }
        //                }
        //            }
        //            //sleepAlertRUN = false;
        //        }
        //        Thread.Sleep(1);
        //    }
        //}
        void restoreBGM()
        {
            try
            {
                string music_path = scriptCOM.GetValue("bg_music");
                music_path = game.Option.SoundPath + music_path;
                if (scriptCOM.GetValue("playing_music") != music_path)
                {
                    if (music_path != "non_music" && music_path != "" && music_path != "null")
                    {
                        scriptCOM.IS("music loop " + music_path);
                    }
                }
            }
            catch { }
        }
        void battleHeartbeat()
        {
            if (BattleIsBusy)
            {
                return;
            }          
            if (haveEnemy == false)
            {
                return;
            }
            if (allEnemySleep)
            {
                return;
            }


            int max_index;
            do
            {
                #region 重新生成行动队列
                if (actQueue.Count == 0)
                {
                    chrIndex.Clear();
                    chrAP.Clear();

                    for (int i = 0; i < CHRs.Count; i++)
                    {
                        //if (!CHRs[i].IsSleeping)
                        {
                            if (CHRs[i].Type == SpriteType.PC || CHRs[i].Type == SpriteType.Monster || (CHRs[i].Type == SpriteType.NPC && CHRs[i].IsEnemy))
                            {
                                chrIndex.Add(i);
                                chrAP.Add(CHRs[i].AP);
                            }
                        }
                    }

                    for (int i = 0; i < chrAP.Count; i++)
                    {
                        bool haveEx = false;
                        for (int j = chrAP.Count; j - 1 > i; j--)
                        {
                            if (chrAP[j - 1] > chrAP[j - 2])
                            {
                                int tmp = chrIndex[j - 2];
                                chrIndex[j - 2] = chrIndex[j - 1];
                                chrIndex[j - 1] = tmp;
                                haveEx = true;
                            }
                        }
                        if (haveEx == false)
                        {
                            break;
                        }
                    }

                    foreach (int i in chrIndex)
                    {
                        actQueue.Enqueue(i);
                    }
                }
                #endregion
                max_index = actQueue.Dequeue();
            }
            while (CHRs[max_index].IsDead || CHRs[max_index].IsSleeping);

            //scriptCOM.AS("focus " + CHRs[max_index].Location.X / SCN.TileSize.Width + " " + CHRs[max_index].Location.Y / SCN.TileSize.Height);
            //
            if (CHRs[max_index].Type == SpriteType.PC)
            {
                if (haveEnemy && !allEnemySleep)
                {
                    if (CHRs[max_index].NeedMove == 0)
                    {
                        scriptCOM.AS(CHRs[max_index].Name + " isfocus");
                    }
                    scriptCOM.AS("menu open 人物战斗 " + CHRs[max_index].Name);
                }
            }
            else if ( CHRs[max_index].Type == SpriteType.Monster || (CHRs[max_index].Type == SpriteType.NPC && CHRs[max_index].IsEnemy))
            {
                CHRs[max_index].AIBattle(game);
            }

            #region check who dead
            for (int i = CHRs.Count - 1; i > -1; i--)
            {
                if (CHRs[i].IsDead)
                {
                    if (CHRs[i].Name == scriptCOM.GetValue("pc_name"))
                    {                        
                        battleReset();
                        scriptCOM.CL();
                        scriptCOM.AppendNScript("dd.nspt");
                    }
                }
            }
            #endregion
            BattleIsBusy = true;
        }
        void battleReset()
        {
            actQueue.Clear();
            chrIndex.Clear();
            chrAP.Clear();
            ClearNPCs();
            ClearDoors();
            BattleIsBusy = false;
        }

        Queue<int> actQueue = new Queue<int>();
        List<int> chrIndex = new List<int>();
        List<int> chrAP = new List<int>();

        
        #endregion*/

        /*
        void BattleHeartbeat()
        {
            if (game.SCN.IsFighting == false)
            {
                return;
            }
            if (actQ == null)
            {
                actQ = new Queue<int>();
            }
            if (actQ.Count == 0)
            {
                int i = 0;
                foreach (NonPlayerCharacter npc in game.SCN.NPCs)
                {
                    if (npc.IsEnemy)
                    {
                        actQ.Enqueue(i);
                        i++;
                    }
                }
                actQ.Enqueue(-1);
            }


            int index = actQ.Peek();
            if (index > -1)
            {
                NonPlayerCharacter npc = game.SCN.NPCs[index];
                npc.IsWaitingCommand = true;
                if (npc.BattleDone)
                {
                    foreach (NonPlayerCharacter n in game.SCN.NPCs)
                    {
                        if (n.BattleDone == false)
                        {
                            return;
                        }
                    }
                    npc.BattleHeartbeat();
                }
                else
                {
                    npc.IsWaitingCommand = false;
                    NextOne();
                }
            }
            else
            {
                foreach (NonPlayerCharacter n in game.SCN.NPCs)
                {
                    if (n.BattleDone == false)
                    {
                        return;
                    }
                }
                if (game.PC.IsWaitingCommand == false)
                {
                    game.OpenPanelbox(menuBattleAct, null);
                }
            }
        }
        public void OnNonPlayerCharacterActCode(object sender, CharacterEventArgs ea)
        {
        }
        Queue<int> actQ;
        public void NextOne()
        {
            actQ.Dequeue();
        }*/

        /*
     void drawZone(Scene scn, Character chr, List<Vector3> zone)
     {
         if (chr.NeedMove > 0)
         {
             return;
         }
         if (chr.Type == SpriteType.Door || chr.Type == SpriteType.Box)
         {
             return;
         }
         if (haveEnemy == false)
         {
             return;
         }

         //List<Vector3> zone = null;
         if (chr.Type == SpriteType.PC)
         {
             //zone = chr.GetCanMoveZone(scn);

             Vector3 v333 = Util.Vector3AddVector3(chr.TargetLocation, scn.Location);
             Rectangle rect = new Rectangle();
             rect.X = (int)v333.X;
             rect.Y = (int)v333.Y;
             rect.Size = scn.TileSize;
             game.Graph.DrawRectangle(Color.FromArgb(160, 0, 255, 0), rect, true);

             foreach (Vector3 v3 in zone)
             {
                 Vector3 v33 = v3;
                 //v33.X *= scn.TileSize.Width;
                 //v33.Y *= scn.TileSize.Height;
                 v33 = Util.Vector3AddVector3(v33, scn.Location);
                 v33 = Util.Vector3AddVector3(v33, chr.Location);
                 Point loc = Util.Vector32Point(v33);
                 loc.X += 1;
                 loc.Y += 1;
                 Size siz = scn.TileSize;
                 siz.Width -= 2;
                 siz.Height -= 2;
                 game.Graph.DrawRectangle(Color.FromArgb(160, 0, 0, 255), new Rectangle(loc, siz), true);
             }
         }
         //else if (chr.Type == SpriteType.NPC)
         //{
         //    zone = chr.GetCanFindZone(chr.Direction, 7, 5, SCN);
         //    if (zone == null)
         //    {
         //        return;
         //    }
         //    foreach (Vector3 v3 in zone)
         //    {
         //        Vector3 v33 = v3;
         //        //v33.X *= scn.TileSize.Width;
         //        //v33.Y *= scn.TileSize.Height;
         //        v33 = Util.Vector3AddVector3(v33, scn.Location);
         //        //v33 = Util.Vector3AddVector3(v33, chr.Location);
         //        Point loc = Util.Vector32Point(v33);
         //        loc.X += 1;
         //        loc.Y += 1;
         //        Size siz = scn.TileSize;
         //        siz.Width -= 2;
         //        siz.Height -= 2;
         //        game.Graph.DrawRectangle(Color.FromArgb(160, 0, 0, 255), new Rectangle(loc, siz), true);
         //    }
         //}
     }

     void drawZones(Scene scn, List<Character> chrs)
     {
         if (SCN != null)
         {
             foreach (Character chr in chrs)
             {
                 if (chr.BattleAct == CharacterActs.BattleMoveCommanding)
                 {
                     drawZone(scn, chr, chr.GetCanMoveZone(scn));
                 }
                 else if (chr.BattleAct == CharacterActs.BattleAttackCommanding)
                 {
                     drawZone(scn, chr, chr.GetCanAttackZone(scn));
                 }
             }
         }
     }
     */
    }
}
